﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace YJKBatchPrinter.Utils
{
	[DesignTimeVisible(true)]
	[Serializable]
	public class CtrlShiftSelTreeView : TreeView
	{
		public bool IsMultiSelect { get; set; }

		public IList<TreeNode> SelectedNodeList
		{
			get
			{
				return this.selectedNodeList;
			}
		}

		public TreeNode LastSelectNode
		{
			get
			{
				return this.currentNode;
			}
			set
			{
				this.currentNode = value;
			}
		}

		public event CtrlShiftSelTreeView.OnDragNodeSucceed TreeNodeCanAcceptDragedHandler;

		public event CtrlShiftSelTreeView.IsNodeCanAcceptDrag IsNodeCanAcceptDragHandler;

		public CtrlShiftSelTreeView()
		{
			base.DrawMode = TreeViewDrawMode.OwnerDrawText;
		}

		protected override void OnNodeMouseClick(TreeNodeMouseClickEventArgs e)
		{
			base.SelectedNode = e.Node;
			if (this.IsMultiSelect)
			{
				if (this.SelectedNodeList.Count != 1 || this.SelectedNodeList[0] != base.SelectedNode)
				{
					if ((Control.ModifierKeys & Keys.Control) != Keys.None || e.Button == MouseButtons.Right)
					{
						this.ctrlMultiSelectNodes(base.SelectedNode, e.Button == MouseButtons.Right);
					}
					else if ((Control.ModifierKeys & Keys.Shift) != Keys.None)
					{
						this.shiftMultiSelectNodes(base.SelectedNode, e.Button == MouseButtons.Right);
					}
					else
					{
						this.singleSelectNode(base.SelectedNode);
					}
				}
			}
			else
			{
				this.singleSelectNode(base.SelectedNode);
				this.setCurrentNode(base.SelectedNode);
			}
			base.Invalidate();
		}

		protected override void OnDrawNode(DrawTreeNodeEventArgs e)
		{
			if (e.Bounds.X == -1)
			{
				return;
			}
			e.DrawDefault = false;
			Font font = this.Font;
			if (e.Node.NodeFont != null)
			{
				font = e.Node.NodeFont;
			}
			Color foreColor = this.ForeColor;
			if (this.SelectedNodeList.Contains(e.Node))
			{
				foreColor = SystemColors.HighlightText;
			}
			else if (e.Node.ForeColor != Color.Empty)
			{
				foreColor = e.Node.ForeColor;
			}
			Graphics graphics = e.Graphics;
			Rectangle rectangle = default(Rectangle);
			rectangle.X = e.Bounds.X;
			rectangle.Y = e.Bounds.Y;
			rectangle.Width = e.Bounds.Width;
			rectangle.Height = e.Bounds.Height;
			if (this.SelectedNodeList.Contains(e.Node))
			{
				graphics.FillRectangle(SystemBrushes.Highlight, rectangle);
				ControlPaint.DrawFocusRectangle(graphics, rectangle, foreColor, SystemColors.Highlight);
				TextRenderer.DrawText(graphics, e.Node.Text, font, rectangle, foreColor, TextFormatFlags.Default);
				return;
			}
			graphics.FillRectangle(SystemBrushes.Window, rectangle);
			TextRenderer.DrawText(graphics, e.Node.Text, font, rectangle, foreColor, TextFormatFlags.Default);
		}

		private void InitializeComponent()
		{
			base.SuspendLayout();
			base.Indent = 25;
			base.ItemHeight = 25;
			base.ResumeLayout(false);
		}

		protected override void OnDragDrop(DragEventArgs drgevent)
		{
			base.OnDragDrop(drgevent);
			TreeNode treeNode = (TreeNode)drgevent.Data.GetData(typeof(TreeNode));
			Point pt = base.PointToClient(new System.Drawing.Point(drgevent.X, drgevent.Y));
			TreeNode nodeAt = base.GetNodeAt(pt);
			if (this.IsNodeCanAcceptDragHandler != null && !this.IsNodeCanAcceptDragHandler(nodeAt))
			{
				return;
			}
			if (!treeNode.Equals(nodeAt) && !this.containsNode(treeNode, nodeAt))
			{
				TreeNode treeNode2 = (TreeNode)treeNode.Clone();
				nodeAt.Nodes.Insert(nodeAt.Index, treeNode2);
				base.SelectedNode = treeNode2;
				treeNode.Remove();
				treeNode = treeNode2;
				treeNode2.Expand();
				if (this.TreeNodeCanAcceptDragedHandler != null)
				{
					this.TreeNodeCanAcceptDragedHandler(treeNode, nodeAt);
				}
			}
		}

		protected override void OnDragEnter(DragEventArgs drgevent)
		{
			base.OnDragEnter(drgevent);
			if (drgevent.Data.GetDataPresent(typeof(TreeNode)))
			{
				drgevent.Effect = DragDropEffects.Move;
				return;
			}
			drgevent.Effect = DragDropEffects.None;
		}

		protected override void OnItemDrag(ItemDragEventArgs e)
		{
			base.OnItemDrag(e);
			if (e.Button == MouseButtons.Left)
			{
				base.DoDragDrop(e.Item, DragDropEffects.Move);
			}
		}

		private void ctrlMultiSelectNodes(TreeNode node, bool mustSelect)
		{
			if (this.SelectedNodeList.Contains(node) && !mustSelect)
			{
				this.SelectedNodeList.Remove(node);
				this.setCurrentNode(this.SelectedNodeList[this.SelectedNodeList.Count - 1]);
				return;
			}
			if (!mustSelect)
			{
				this.SelectedNodeList.Add(node);
				this.setCurrentNode(node);
			}
		}

		private void shiftMultiSelectNodes(TreeNode node, bool mustSelect)
		{
			if (mustSelect)
			{
				return;
			}
			if (this.SelectedNodeList.Contains(node))
			{
				this.SelectedNodeList.Remove(node);
				this.setCurrentNode(this.SelectedNodeList[this.SelectedNodeList.Count - 1]);
				return;
			}
			if (this.currentNode == null)
			{
				this.SelectedNodeList.Clear();
				if (!this.SelectedNodeList.Contains(node))
				{
					this.SelectedNodeList.Add(node);
				}
				this.currentNode = node;
			}
			if (node.Parent == this.currentNode.Parent)
			{
				TreeNode treeNode = node;
				for (int i = Math.Abs(this.currentNode.Index - node.Index); i > 0; i--)
				{
					if (!this.SelectedNodeList.Contains(treeNode))
					{
						this.SelectedNodeList.Add(treeNode);
					}
					treeNode = ((this.currentNode.Index > node.Index) ? treeNode.NextNode : treeNode.PrevNode);
				}
				this.setCurrentNode(node);
				return;
			}
			this.singleSelectNode(base.SelectedNode);
		}

		private void singleSelectNode(TreeNode node)
		{
			this.SelectedNodeList.Clear();
			this.SelectedNodeList.Add(node);
			this.setCurrentNode(node);
		}

		private void setCurrentNode(TreeNode node)
		{
			if (this.currentNode != node)
			{
				this.currentNode = node;
			}
		}

		private bool containsNode(TreeNode parentNode, TreeNode childNode)
		{
			return childNode.Parent != null && (childNode.Parent.Equals(parentNode) || this.containsNode(parentNode, childNode.Parent));
		}

		private IList<TreeNode> selectedNodeList = new List<TreeNode>();

		private TreeNode currentNode;

		public delegate void OnDragNodeSucceed(TreeNode sourceNode, TreeNode targetNode);

		public delegate bool IsNodeCanAcceptDrag(TreeNode targetNode);
	}
}
